
import { _decorator, Component, director, Node, TiledMap } from 'cc';
import { TileMapManager } from '../Tile/TileMapManager';
import { createUINode } from '../../Utils';
import level from '../../Levels/levels1';
const { ccclass, property } = _decorator;
import Levels, { ILevel } from '../../Levels/index'
import DataManager, { IRecord } from '../../Runtime/DataManager';
import { TILE_HEIGHT, TILE_WIDTH } from '../Tile/TileManager';
import EventManager from '../../Runtime/EventManager';
import { DIRECTION_ENUM, ENTITY_STATE_ENUM, ENTITY_TYPE_ENUM, EVENT_ENUM, SCENE_ENUM } from '../../Enum';
import { PlayerManager } from '../Player/PlayerManager';
import { WoodenSkeletonManage } from '../WoodenSkeleton/WoodenSkeletonManage';
import { DoorManager } from '../Door/DoorManager';
import { IronSkeletonManager } from '../IronSkeleton/IronSkeletonManager';
import { BurstManager } from '../Burst/BurstManager';
import { SpikesManager } from '../Spikes/SpikesManager';
import FaderManager from '../../Runtime/FaderManager';
import { ShakeManage } from '../UI/ShakeManage';

//场景的总管理  
@ccclass('BattleManage')
export class BattleManage extends Component {
    level: ILevel
    stage: Node

    onLoad() {
        DataManager.Instance.levelIndex = 1
        EventManager.Instance.on(EVENT_ENUM.NEXT_LEVEL, this.nextLevel, this)  //通过事件中心绑定
        EventManager.Instance.on(EVENT_ENUM.PLAYER_MOVE_END, this.cheekArrived, this)  //通过事件中心绑定


        EventManager.Instance.on(EVENT_ENUM.RECORD_STEP, this.record, this)  //通过事件中心绑定

        EventManager.Instance.on(EVENT_ENUM.REVOKE_STEP, this.revoke, this)  //通过事件中心绑定



        EventManager.Instance.on(EVENT_ENUM.RESTART_LEVEL, this.initLevel, this)  //通过事件中心绑定

        EventManager.Instance.on(EVENT_ENUM.QUIT_BATTLE, this.quitBattle, this)  //通过事件中心绑定


    }

    onDestroy() {
        EventManager.Instance.off(EVENT_ENUM.NEXT_LEVEL, this.nextLevel)

        EventManager.Instance.off(EVENT_ENUM.PLAYER_MOVE_END, this.cheekArrived)  //通过事件中心绑定



        EventManager.Instance.off(EVENT_ENUM.RECORD_STEP, this.record)  //通过事件中心绑定

        EventManager.Instance.off(EVENT_ENUM.REVOKE_STEP, this.revoke)  //通过事件中心绑定
    }



    start() {
        this.generateStage()
        this.initLevel()



    }

    async initLevel() {
        const level = Levels[`level${DataManager.Instance.levelIndex}`]

        if (level) {
            await FaderManager.Instance.fadeIn()
            this.clearLevel()


            this.level = level

            //吧数据存到数据中心里
            DataManager.Instance.mapInfo = this.level.mapInfo
            DataManager.Instance.mapColumnCount = this.level.mapInfo[0].length || 0
            DataManager.Instance.mapRowCount = this.level.mapInfo.length || 0


            await Promise.all([this.generateTileMap(),  //生成地图
            this.generateBursts(), //地裂

            this.generateSpikes(), //地刺

            this.generateDoor(), //生成人物

            this.generatePlayer(), //生成人物
            this.generateEnemies(), //生成敌人
            ]
            )



            // this.generateTileMap()  //生成地图
            // this.generateBursts() //地裂

            // this.generateSpikes() //地刺

            // this.generateDoor() //生成人物

            // this.generatePlayer() //生成人物
            // this.generateEnemies() //生成敌人




            await FaderManager.Instance.fadeOut()
        }
    }



    async generateSpikes() {

        // const spikes = createUINode()

        // spikes.setParent(this.stage)

        // const spikesManager = spikes.addComponent(SpikesManager)
        // await spikesManager.init({
        //     x: 2,
        //     y: 6,
        //     type: ENTITY_TYPE_ENUM.SPIKES_FOUR,
        //     count: 0,
        // })
        // DataManager.Instance.spikes.push(spikesManager)


        const primise = []
        for (let i = 0; i < this.level.spikes.length; i++) {
            const spikes = this.level.spikes[i]


            const node = createUINode()

            node.setParent(this.stage)
            const spikesManager = node.addComponent(SpikesManager)
            // await manager.init(enemy)
            primise.push(spikesManager.init(spikes))
            DataManager.Instance.spikes.push(spikesManager)

        }

        await Promise.all(primise)


    }

    async generateBursts() {
        // const burst = createUINode()

        // burst.setParent(this.stage)

        // const burstManager = burst.addComponent(BurstManager)
        // await burstManager.init({
        //     x: 7,
        //     y: 6,
        //     type: ENTITY_TYPE_ENUM.BURST,
        //     direction: DIRECTION_ENUM.TOP,
        //     state: ENTITY_STATE_ENUM.IDLE
        // })
        // DataManager.Instance.burst.push(burstManager)



        // const primise =[]
        // for (let i = 0; i < this.level.enemies.length; i++) {
        //     const burst = this.level.bursts[i]


        //     const node = createUINode()

        //     node.setParent(this.stage)
        //     const burstManager = node.addComponent(BurstManager)
        //     // await manager.init(enemy)
        //     primise.push(burstManager.init(burst))
        //     DataManager.Instance.burst.push(burstManager)

        // }

        // await Promise.all(primise)

        const promises = []
        for (let i = 0; i < this.level.bursts.length; i++) {
            const burst = this.level.bursts[i]
            const node = createUINode()
            node.setParent(this.stage)
            const burstManager = node.addComponent(BurstManager)
            promises.push(burstManager.init(burst))
            DataManager.Instance.bursts.push(burstManager)
        }
        await Promise.all(promises)

    }

    async generateDoor() {
        const door = createUINode()

        door.setParent(this.stage)

        const doorManager = door.addComponent(DoorManager)
        await doorManager.init(this.level.door)
        DataManager.Instance.door = doorManager

    }


    async generateEnemies() {


        const primise = []
        for (let i = 0; i < this.level.enemies.length; i++) {
            const enemy = this.level.enemies[i]


            const node = createUINode()

            node.setParent(this.stage)
            const Manager = enemy.type === ENTITY_TYPE_ENUM.SKELETON_WOODEN ? WoodenSkeletonManage : IronSkeletonManager
            const manager = node.addComponent(Manager)
            // await manager.init(enemy)
            primise.push(manager.init(enemy))
            DataManager.Instance.enemies.push(manager)

        }

        await Promise.all(primise)

        // const emeny = createUINode()

        // emeny.setParent(this.stage)

        // const woodenSkeletonManage = emeny.addComponent(WoodenSkeletonManage)
        // await woodenSkeletonManage.init({
        //     x: 2,
        //     y: 4,
        //     type: ENTITY_TYPE_ENUM.SKELETON_WOODEN,
        //     direction: DIRECTION_ENUM.TOP,
        //     state: ENTITY_STATE_ENUM.IDLE
        // })

        // DataManager.Instance.enemies.push(woodenSkeletonManage)



        //

        // const emeny2 = createUINode()

        // emeny2.setParent(this.stage)

        // const ironSkeletonManage = emeny2.addComponent(IronSkeletonManager)
        // await ironSkeletonManage.init({
        //     x: 2,
        //     y: 2,
        //     type: ENTITY_TYPE_ENUM.SKELETON_IRON,
        //     direction: DIRECTION_ENUM.TOP,
        //     state: ENTITY_STATE_ENUM.IDLE
        // })

        // DataManager.Instance.enemies.push(ironSkeletonManage)


    }
    async generatePlayer() {
        const player = createUINode()

        player.setParent(this.stage)

        const playerManager = player.addComponent(PlayerManager)
        await playerManager.init(this.level.player
            //     {
            //     x: 2,
            //     y: 7,
            //     type: ENTITY_TYPE_ENUM.PLAYER,
            //     direction: DIRECTION_ENUM.TOP,
            //     state: ENTITY_STATE_ENUM.IDLE
            // }
        )
        DataManager.Instance.player = playerManager
        EventManager.Instance.emit(EVENT_ENUM.PLAYER_BORN, true)//玩家生成的时候触发这个事件

    }

    //下一个关卡切换
    nextLevel() {
        DataManager.Instance.levelIndex++
        this.initLevel()

    }

    clearLevel() {

        this.stage.destroyAllChildren()

        //重置数据中心里的数据
        DataManager.Instance.reset()
    }

    async generateTileMap() {

        const tileMap = createUINode()

        tileMap.setParent(this.stage)

        const tilemapmanager = tileMap.addComponent(TileMapManager)
        await tilemapmanager.init()

        this.adaptPos()//适配屏幕的方法
    }
    // update (deltaTime: number) {
    //     // [4]
    // }


    adaptPos() {
        const { mapColumnCount, mapRowCount } = DataManager.Instance

        const diX = TILE_WIDTH * mapRowCount / 2

        const diY = TILE_HEIGHT * mapColumnCount / 2

        this.stage.getComponent(ShakeManage).stop()





        this.stage.setPosition(-diX, diY + 80)
        //实现的思路---这个地图的左上角是她的原点，只需要偏移x，y的一半即可
        //先获取地图的大小---需要数据中心存放数据？





    }



    cheekArrived() {
        const { x: playx, y: playy } = DataManager.Instance.player
        const { x: doorx, y: doory, state: doorState } = DataManager.Instance.door

        if (playx === doorx && playy === doory && doorState === ENTITY_STATE_ENUM.DEATH) {
            EventManager.Instance.emit(EVENT_ENUM.NEXT_LEVEL)

        }

    }

    generateStage() {
        this.stage = createUINode()

        this.stage.setParent(this.node)

        this.stage.addComponent(ShakeManage)
    }

    //记录数据
    record() {
        const item: IRecord = {
            player: {
                x: DataManager.Instance.player.x,
                y: DataManager.Instance.player.y,
                direction: DataManager.Instance.player.direction,
                state: DataManager.Instance.player.state === ENTITY_STATE_ENUM.IDLE || DataManager.Instance.player.state === ENTITY_STATE_ENUM.DEATH || DataManager.Instance.player.state === ENTITY_STATE_ENUM.AIRDEATH ? DataManager.Instance.player.state : ENTITY_STATE_ENUM.IDLE,
                type: DataManager.Instance.player.type,
            },
            door: {
                x: DataManager.Instance.door.x,
                y: DataManager.Instance.door.y,
                direction: DataManager.Instance.door.direction,
                state: DataManager.Instance.door.state,
                type: DataManager.Instance.door.type,
            },

            enemies: DataManager.Instance.enemies.map(({ x, y, direction, state, type }) =>
                ({ x, y, direction, state, type })),

            bursts: DataManager.Instance.bursts.map(({ x, y, direction, state, type }) =>
                ({ x, y, direction, state, type })),

            spikes: DataManager.Instance.spikes.map(({ x, y, count, type }) =>
                ({ x, y, count, type })),



        }
        //保存
        DataManager.Instance.records.push(item)


    }

    //撤回
    revoke() {

        const item = DataManager.Instance.records.pop()

        if (item) {
            DataManager.Instance.player.x = DataManager.Instance.player.targetX = item.player.x
            DataManager.Instance.player.y = DataManager.Instance.player.targetY = item.player.y
            DataManager.Instance.player.direction = item.player.direction
            DataManager.Instance.player.state = item.player.state




            DataManager.Instance.door.x = item.door.x
            DataManager.Instance.door.y = item.door.y
            DataManager.Instance.door.direction = item.door.direction
            DataManager.Instance.door.state = item.door.state



            for (let i = 0; i < item.enemies.length; i++) {
                const item1 = item.enemies[i]
                DataManager.Instance.enemies[i].x = item1.x
                DataManager.Instance.enemies[i].y = item1.y
                DataManager.Instance.enemies[i].state = item1.state
                DataManager.Instance.enemies[i].direction = item1.direction
            }

            for (let i = 0; i < item.spikes.length; i++) {
                const item1 = item.spikes[i]
                DataManager.Instance.spikes[i].x = item1.x
                DataManager.Instance.spikes[i].y = item1.y
                DataManager.Instance.spikes[i].count = item1.count
            }

            for (let i = 0; i < item.bursts.length; i++) {
                const item1 = item.bursts[i]
                DataManager.Instance.bursts[i].x = item1.x
                DataManager.Instance.bursts[i].y = item1.y
                DataManager.Instance.bursts[i].state = item1.state
            }
        }

    }



    quitBattle() {

        this.node.destroy()
        director.loadScene(SCENE_ENUM.Start)
    }
}





